package com.own.component.util.math.util;

import com.own.component.util.math.exception.MathException;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * AbstractCalculateUtil
 *
 * @author chenxueli
 * @date 2022-06-15 03:14:15
 */
@Slf4j
public abstract class AbstractCalculateUtil<VALUE_TYPE, DATA_TYPE> {

    protected static final String VALUE_FIELD = "value";
    protected static final String VALUE_PARAM = "${" + VALUE_FIELD + "}";

    /**
     * 计算
     *
     * @param expression 表达式信息
     * @return 值信息
     * @author chenxueli
     * @date 2022-06-15 03:14:15
     */
    public abstract VALUE_TYPE calculate(String expression);

    /**
     * 计算
     *
     * @param expression 表达式信息
     * @param value      传入的参数值信息
     * @return 值信息
     * @author chenxueli
     * @date 2022-06-15 03:14:15
     */
    public VALUE_TYPE calculate(String expression, DATA_TYPE value) {
        var map = new HashMap<String, DATA_TYPE>(4);
        map.put(VALUE_FIELD, value);
        return calculate(expression, map);
    }

    /**
     * 计算
     *
     * @param formula 公式信息
     * @param dataMap 数据信息
     * @return 值信息
     * @author chenxueli
     * @date 2022-06-15 03:14:15
     */
    public VALUE_TYPE calculate(String formula, Map<String, DATA_TYPE> dataMap) {
        return calculate(buildExpression(formula, dataMap));
    }

    /**
     * 公式变量转换
     *
     * @param formula 表达式
     * @param data    数据信息
     * @return 转换后的内容
     * @author chenxueli
     * @date 2022-06-15 03:14:15
     */
    @SuppressWarnings("all")
    protected String buildExpression(String formula, Map<String, DATA_TYPE> data) {
        var regex = "\\$\\{(.+?)\\}";
        var pattern = Pattern.compile(regex);
        var matcher = pattern.matcher(removeMissDataTag(formula));
        var buffer = new StringBuffer();
        while (matcher.find()) {
            var key = matcher.group(1);
            if (!data.containsKey(key)) {
                throw new MathException("计算变量：$\\{{}\\}不存在值", key);
            }
            var value = data.get(key);
            matcher.appendReplacement(buffer, value == null ? "" : value instanceof String ? (String) value : value.toString());
        }
        matcher.appendTail(buffer);
        return buffer.toString();
    }

    /**
     * 获取公式中所有的参数信息
     *
     * @param formula 表达式
     * @return 变量列表信息
     * @author chenxueli
     * @date 2022-06-15 03:14:15
     */
    @SuppressWarnings("all")
    public List<String> listVar(String formula) {
        // 预处理公式
        var varList = new ArrayList<String>();
        var regex = "\\$\\{(.+?)\\}";
        var pattern = Pattern.compile(regex);
        var matcher = pattern.matcher(removeMissData(formula));
        while (matcher.find()) {
            varList.add(matcher.group(1));
        }
        return varList;
    }

    /**
     * 移除所有的Data数据
     *
     * @param formula 公式信息
     * @return 移除后的公式信息
     */
    private String removeMissData(String formula) {
        return formula.replaceAll("<!DATA>.*?</DATA>", "");
    }

    /**
     * 移除所有的Data标签
     *
     * @param formula 公式信息
     * @return 移除后的公式信息
     */
    private String removeMissDataTag(String formula) {
        return formula.replaceAll("<!DATA>|</DATA>", "");
    }

}
